{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 程序说明\n",
    "时间：2016年11月16日\n",
    "\n",
    "说明：该程序是一个包含两个隐藏层的神经网络，程序会保存每轮训练的acc和loss，并且绘制它们。\n",
    "\n",
    "数据集：MNIST"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.加载keras模块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from __future__ import print_function\n",
    "import numpy as np\n",
    "np.random.seed(1337)  # for reproducibility"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import keras\n",
    "from keras.datasets import mnist\n",
    "from keras.models import Sequential\n",
    "from keras.layers.core import Dense, Dropout, Activation\n",
    "from keras.optimizers import SGD, Adam, RMSprop\n",
    "from keras.utils import np_utils\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 写一个LossHistory类，保存loss和acc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "class LossHistory(keras.callbacks.Callback):\n",
    "    def on_train_begin(self, logs={}):\n",
    "        self.losses = {'batch':[], 'epoch':[]}\n",
    "        self.accuracy = {'batch':[], 'epoch':[]}\n",
    "        self.val_loss = {'batch':[], 'epoch':[]}\n",
    "        self.val_acc = {'batch':[], 'epoch':[]}\n",
    "\n",
    "    def on_batch_end(self, batch, logs={}):\n",
    "        self.losses['batch'].append(logs.get('loss'))\n",
    "        self.accuracy['batch'].append(logs.get('acc'))\n",
    "        self.val_loss['batch'].append(logs.get('val_loss'))\n",
    "        self.val_acc['batch'].append(logs.get('val_acc'))\n",
    "        \n",
    "    def on_epoch_end(self, batch, logs={}):\n",
    "        self.losses['epoch'].append(logs.get('loss'))\n",
    "        self.accuracy['epoch'].append(logs.get('acc'))\n",
    "        self.val_loss['epoch'].append(logs.get('val_loss'))\n",
    "        self.val_acc['epoch'].append(logs.get('val_acc'))\n",
    "        \n",
    "    def loss_plot(self, loss_type):\n",
    "        iters = range(len(self.losses[loss_type]))\n",
    "        plt.figure()\n",
    "        # acc\n",
    "        plt.plot(iters, self.accuracy[loss_type], 'r', label='train acc')\n",
    "        # loss\n",
    "        plt.plot(iters, self.losses[loss_type], 'g', label='train loss')\n",
    "        if loss_type == 'epoch':\n",
    "            # val_acc\n",
    "            plt.plot(iters, self.val_acc[loss_type], 'b', label='val acc')\n",
    "            # val_loss\n",
    "            plt.plot(iters, self.val_loss[loss_type], 'k', label='val loss')\n",
    "        plt.grid(True)\n",
    "        plt.xlabel(loss_type)\n",
    "        plt.ylabel('acc-loss')\n",
    "        plt.legend(loc=\"upper right\")\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.变量初始化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size = 128 \n",
    "nb_classes = 10\n",
    "nb_epoch = 20"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.准备数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "60000 train samples\n",
      "10000 test samples\n"
     ]
    }
   ],
   "source": [
    "# the data, shuffled and split between train and test sets\n",
    "(X_train, y_train), (X_test, y_test) = mnist.load_data()\n",
    "\n",
    "X_train = X_train.reshape(60000, 784)\n",
    "X_test = X_test.reshape(10000, 784)\n",
    "X_train = X_train.astype('float32')\n",
    "X_test = X_test.astype('float32')\n",
    "X_train /= 255\n",
    "X_test /= 255\n",
    "print(X_train.shape[0], 'train samples')\n",
    "print(X_test.shape[0], 'test samples')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 转换类标号"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# convert class vectors to binary class matrices\n",
    "Y_train = np_utils.to_categorical(y_train, nb_classes)\n",
    "Y_test = np_utils.to_categorical(y_test, nb_classes)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.建立模型\n",
    "### 使用Sequential（）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "model = Sequential()\n",
    "model.add(Dense(512, input_shape=(784,)))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Dropout(0.2))\n",
    "model.add(Dense(512))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Dropout(0.2))\n",
    "model.add(Dense(10))\n",
    "model.add(Activation('softmax'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 打印模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "____________________________________________________________________________________________________\n",
      "Layer (type)                     Output Shape          Param #     Connected to                     \n",
      "====================================================================================================\n",
      "dense_1 (Dense)                  (None, 512)           401920      dense_input_1[0][0]              \n",
      "____________________________________________________________________________________________________\n",
      "activation_1 (Activation)        (None, 512)           0           dense_1[0][0]                    \n",
      "____________________________________________________________________________________________________\n",
      "dropout_1 (Dropout)              (None, 512)           0           activation_1[0][0]               \n",
      "____________________________________________________________________________________________________\n",
      "dense_2 (Dense)                  (None, 512)           262656      dropout_1[0][0]                  \n",
      "____________________________________________________________________________________________________\n",
      "activation_2 (Activation)        (None, 512)           0           dense_2[0][0]                    \n",
      "____________________________________________________________________________________________________\n",
      "dropout_2 (Dropout)              (None, 512)           0           activation_2[0][0]               \n",
      "____________________________________________________________________________________________________\n",
      "dense_3 (Dense)                  (None, 10)            5130        dropout_2[0][0]                  \n",
      "____________________________________________________________________________________________________\n",
      "activation_3 (Activation)        (None, 10)            0           dense_3[0][0]                    \n",
      "====================================================================================================\n",
      "Total params: 669706\n",
      "____________________________________________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5.训练与评估\n",
    "### 编译模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "model.compile(loss='categorical_crossentropy',\n",
    "              optimizer=RMSprop(),\n",
    "              metrics=['accuracy'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 创建一个实例history"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "history = LossHistory()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 迭代训练（注意这个地方要加入callbacks）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 60000 samples, validate on 10000 samples\n",
      "Epoch 1/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.2448 - acc: 0.9239 - val_loss: 0.1220 - val_acc: 0.9623\n",
      "Epoch 2/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.1025 - acc: 0.9689 - val_loss: 0.0775 - val_acc: 0.9760\n",
      "Epoch 3/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0752 - acc: 0.9773 - val_loss: 0.0792 - val_acc: 0.9775\n",
      "Epoch 4/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0608 - acc: 0.9819 - val_loss: 0.0758 - val_acc: 0.9790\n",
      "Epoch 5/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0500 - acc: 0.9852 - val_loss: 0.0903 - val_acc: 0.9766\n",
      "Epoch 6/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0449 - acc: 0.9863 - val_loss: 0.0780 - val_acc: 0.9798\n",
      "Epoch 7/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0398 - acc: 0.9875 - val_loss: 0.0798 - val_acc: 0.9823\n",
      "Epoch 8/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0349 - acc: 0.9899 - val_loss: 0.0794 - val_acc: 0.9834\n",
      "Epoch 9/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0301 - acc: 0.9912 - val_loss: 0.0932 - val_acc: 0.9805\n",
      "Epoch 10/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0281 - acc: 0.9919 - val_loss: 0.0819 - val_acc: 0.9842\n",
      "Epoch 11/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0276 - acc: 0.9921 - val_loss: 0.1007 - val_acc: 0.9814\n",
      "Epoch 12/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0250 - acc: 0.9931 - val_loss: 0.0978 - val_acc: 0.9824\n",
      "Epoch 13/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0228 - acc: 0.9935 - val_loss: 0.1063 - val_acc: 0.9827\n",
      "Epoch 14/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0234 - acc: 0.9939 - val_loss: 0.1014 - val_acc: 0.9815\n",
      "Epoch 15/20\n",
      "60000/60000 [==============================] - 4s - loss: 0.0188 - acc: 0.9946 - val_loss: 0.1052 - val_acc: 0.9839\n",
      "Epoch 16/20\n",
      "60000/60000 [==============================] - 4s - loss: 0.0180 - acc: 0.9946 - val_loss: 0.1027 - val_acc: 0.9833\n",
      "Epoch 17/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0213 - acc: 0.9946 - val_loss: 0.1103 - val_acc: 0.9840\n",
      "Epoch 18/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0204 - acc: 0.9949 - val_loss: 0.1168 - val_acc: 0.9818\n",
      "Epoch 19/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0185 - acc: 0.9954 - val_loss: 0.1318 - val_acc: 0.9809\n",
      "Epoch 20/20\n",
      "60000/60000 [==============================] - 5s - loss: 0.0194 - acc: 0.9954 - val_loss: 0.1173 - val_acc: 0.9831\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x7f1ef8066590>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.fit(X_train, Y_train,\n",
    "            batch_size=batch_size, nb_epoch=nb_epoch,\n",
    "            verbose=1, \n",
    "            validation_data=(X_test, Y_test),\n",
    "            callbacks=[history])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 模型评估"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test score: 0.117298825225\n",
      "Test accuracy: 0.9831\n"
     ]
    }
   ],
   "source": [
    "score = model.evaluate(X_test, Y_test, verbose=0)\n",
    "print('Test score:', score[0])\n",
    "print('Test accuracy:', score[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 绘制acc-loss曲线"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\nrriCoqIiBg0axAknnMDpgYNc2qm1JJKTk8P8+fOZOXMm+fn5vPjii1xwwQXB50855RQWLlzIzTff\nTG5uLlOnTmXHjh0APPfcc6SmpnLcccdRUFDA448/HlVMnZXcJ7gZY+Iq0U9w60nsBDfTadYn7ixr\nT9OdWGIwxhgTxrqSjDEdZl1JicO6kowxxsSMJYYeyvrEnWXtaboTSwzGGGPC2BiDMabDbIwhcdgY\ngzHGmJixxNBDWZ+4s6w9u6/O3Npz2rRpPP300w5HFHvJdT8GY4yJghO39vz973/vYETJwfYYeii7\nto+zrD2Tk93aMzJLDMaYbikRbu0ZSlW59957KS4uZsCAAcyZMyd4ae36+npmz55Nv379yMvL41vf\n+hb79+8HfLcHHT58OL1792b48OG88MILDrZSZJYYeijrE3eWtWfiefbZZykqKuKNN96goqKCf/u3\nfws+F7i151tvvQX4bu25detWvv76ayZNmsRll13W6npDb+355JNPcv3113P48OGjxrNw4UKeffZZ\n3n//fbZt20ZlZSU33ngjAM888wwVFRWUlZVx8OBBnnjiCTIzM6mpqeGmm27irbfeoqKigo8//pgJ\nEyZ0smWOzsYYjDExJf/e+XsbAOgvO3ZYbPNDOEWEf//3fyczMzNYN2fOnOD03XffzWOPPUZlZSW9\nevVqsb60tDTuuusuXC4XM2bMICcnh02bNjF58uQ243j++ee55ZZbGDp0KAAPPPAA48aNY+HChbjd\nbr755hs2b97MuHHjmDhxIgA1NTWkpKSwZs0aBg8eTEFBAQUFBR1qh2hYYuihrE/cWdaerevoBj2W\nmt/a8+c//zkvv/wyBw4cQESCt/aMlBiiubVnqN27dweTAsDQoUNpaGhg3759zJ49m127dnHJJZdw\n+PBhLr/8cu677z6ysrJ46aWXePjhh7n66qs588wzeeSRRxg9enQnW6Bt1pVkjOm24nlrz+YGDhxI\naWlpcL60tBS3201BQQGpqancddddrFu3jo8//pjXX3+dZ599FoDvfOc7LFmyhL179zJ69GiuvfZa\nR+OKxBJDD2V94s6y9kxM8by1Z3OzZs3i0UcfZfv27VRVVXHnnXdyySWX4HK5KCkpYe3atXi9XnJy\ncnC73bhcLr7++mtee+01ampqcLvd5OTkkJKS4nhszVliMMZ0W/G8tWfz566++mpmz57NWWedxfDh\n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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f200c10c690>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "history.loss_plot('epoch')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.12"
  },
  "ssap_exp_config": {
   "error_alert": "Error Occurs!",
   "initial": [],
   "max_iteration": 1000,
   "recv_id": "",
   "running": [],
   "summary": [],
   "version": "1.1.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
